
/******************************************************************/
/* 				SVRIPC.C						*/
/* This file implements Generic MOL IPC primitives			*/
/* UDP Sockets can be replaced by other abstractions or protocols */
/******************************************************************/
#define _GNU_SOURCE 
#include <stdio.h>
#include <stdint.h> 
#include <dlfcn.h> 
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <signal.h>
#include <sys/syslog.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>


/*---------------------- MINIX HEADERS ---------------------------*/

#include "../include/minix/config.h" 	
#include "../include/minix/endpoint.h" 	
#include "../../kernel/ipc.h"			

/* #include "../../kernel/const.h"  	*/
/* #include "../../kernel/type.h"		*/
/* #include "../../kernel/priv.h"		*/
/* #include "../../kernel/com.h"		*/
/* #include "../../kernel/endpoint.h"	*/

/*---------------------- MOL HEADERS -----------------------------*/
#include "../include/mol/molminix.h" 
#define MOLDBG 1
#include "../include/mol/mollib.h" 
#define _SYSTEM
#include "../include/mol/molerr.h" 

/*---------------------- MOLKERNEL HEADERS -------------------------*/
#include "molproc.h"
#include "proc.h"
#include "svripc.h"

extern ipc_t 		mk_ipc;			/* defines IPC struct	*/
extern struct kproc	kproc[];		/* kernel process table */
extern pid_t		kpid;			/* spid of MOLKERNEL		*/


/*----------------------------------------------------------*/
/*			svr_open 						*/
/* Initialize MOL CONTROL and IPC Channels			*/
/*----------------------------------------------------------*/
int svr_open(ipc_t *ctrl_ipc, ipc_t *ipc_ipc)
{
    	int rcode;
	
	/* Creates the CONTROL socket		*/ 
	ctrl_ipc->socket = socket(AF_INET,SOCK_DGRAM,0);
	if ( ctrl_ipc->socket == -1 )
		MOLERROR("socket=%d\n",ctrl_ipc->socket);

	/* Creates the IPC socket		*/ 
	ipc_ipc->socket = socket(AF_INET,SOCK_DGRAM,0);
	if ( ipc_ipc->socket == -1 )
		MOLERROR("socket=%d\n",ipc_ipc->socket);
		
	memset(&ctrl_ipc->addr,0,sizeof(ctrl_ipc->addr));
	memset(&ipc_ipc->addr ,0,sizeof(ipc_ipc->addr) );
	
    ctrl_ipc->svr_addr.sin_family = ipc_ipc->svr_addr.sin_family = AF_INET;
	
    ctrl_ipc->svr_addr.sin_port = htons(MOLKERNEL_PORT);
	ipc_ipc->svr_addr.sin_port  = htons(MOLKERNEL_PORT+1);
	
   	ipc_ipc->svr_addr.sin_addr.s_addr 	= 
	ctrl_ipc->svr_addr.sin_addr.s_addr 	= inet_addr(MOLKERNEL_ADDR);
	
   	if( ctrl_ipc->addr.sin_addr.s_addr == INADDR_NONE )
        	MOLERROR("bad address %d\n",INADDR_NONE);

OLDEBUG("Control Channel on %s:%d\n", MOLKERNEL_ADDR, MOLKERNEL_PORT);
   	NO_EINTR(rcode = bind(ctrl_ipc->socket
    	        ,(struct sockaddr *)&ctrl_ipc->svr_addr
    	        ,sizeof(struct sockaddr_in)));
	if ( rcode < 0 )
	  	MOLERROR("Control socket bind rcode=%d\n",rcode);
		
OLDEBUG("IPC Channel on %s:%d\n", MOLKERNEL_ADDR, MOLKERNEL_PORT+1);
   	NO_EINTR(rcode = bind(ipc_ipc->socket
    	        ,(struct sockaddr *)&ipc_ipc->svr_addr
    	        ,sizeof(struct sockaddr_in)));
	if ( rcode < 0 )
	  	MOLERROR("IPC socket bind rcode=%d\n",rcode);
		
	return(OK);
}

/*----------------------------------------------------------*/
/*			svr_send						*/
/* Send an MoL message 			 				*/
/*----------------------------------------------------------*/
int svr_send(ipc_t *pipc)
{
	int bytes;
	unsigned int addr_len;

    pipc->molmsg.spid = kpid;

OLDEBUG("code=%X spid=%d seq=%ld srcdst=%d\n",
                	pipc->molmsg.code,
                	pipc->molmsg.spid,
                	pipc->molmsg.seq,
			pipc->molmsg.srcdst);

	addr_len = sizeof (struct sockaddr_in);
	NO_EINTR(bytes = sendto(pipc->socket,  		/* Socket to send 	 	*/
			&pipc->molmsg,		/* The datagram result to snd */
			sizeof(mol_msg_t), 	/* The datagram length 		*/
			0,              		/* Flags: no options 		*/
			(struct sockaddr *)&pipc->addr, /* Destination address */
			addr_len)); 			/* Destination address length */

     	if( bytes < 0)
      	MOLERROR(" sendto bytes=%d\n",bytes);
	return(OK);
}

/*----------------------------------------------------------*/
/*			svr_rcv 						*/
/* Receive MoL message 							*/
/*----------------------------------------------------------*/
int svr_rcv(ipc_t *pipc)
{
    unsigned int addr_len;
    int bytes;
	proc_nr_t src_p;
	struct kproc *sptr;

OLDEBUG("code=%X spid=%d seq=%ld\n",
                pipc->molmsg.code,
                pipc->molmsg.spid,
                pipc->molmsg.seq);

	addr_len = sizeof (struct sockaddr_in);
	NO_EINTR(bytes = recvfrom(pipc->socket,		/* Socket to receive */
			&pipc->molmsg,		/* Receiving buffer */
			sizeof(mol_msg_t),    	/* Max recv buf size */
			0,              		/* Flags: no options */
			(struct sockaddr *)&pipc->addr,  /* Destination address */
			&addr_len));  		/* Addr len, in & out */

      if( bytes < 0)
       	MOLERROR(" recvfrom bytes=%d\n",bytes);

			
    src_p = check_endpoint(pipc->molmsg.p_endpoint);
	if( src_p != NONE )
			{
			sptr = &kproc[src_p+NR_TASKS];
			sptr->p_hello = 0;			/* don't need to start hello	*/
			sptr->p_dead = 0;				/* the process is not dead 	*/
			}	
	return(OK);
}

/*----------------------------------------------------------*/
/*			svr_close						*/
/* Close IPC 								*/
/*----------------------------------------------------------*/
int svr_close(ipc_t *ctrl_ipc, ipc_t *ipc_ipc)
{
OLDEBUG("\n");
	int rcode;

	rcode = close(ctrl_ipc->socket);
	if ( rcode < 0 )
	  	MOLERROR("socket close rcode=%d\n",rcode);
	
	rcode = close(ipc_ipc->socket);
	if ( rcode < 0 )
	  	MOLERROR("socket close rcode=%d\n",rcode);

	return(OK);
	
}

/*----------------------------------------------------------*/
/*			svr_data_send			*/
/* Send RAW data  				*/
/*----------------------------------------------------------*/
int svr_data_send(ipc_t *ctrl_ipc, char *buf_ptr, int nbytes)
{
	int bytes;
	unsigned int addr_len;

    ctrl_ipc->molmsg.spid = kpid;
	addr_len = sizeof (struct sockaddr_in);

	NO_EINTR(bytes = sendto(ctrl_ipc->socket,  		/* Socket to send 	 	*/
			buf_ptr,								/* The datagram result to snd */
			nbytes, 								/* The datagram length 		*/
			0,              						/* Flags: no options 		*/
			(struct sockaddr *)&ctrl_ipc->addr, 	/* Destination address */
			addr_len)); 							/* Destination address length */

   	if( bytes < 0)
      	MOLERROR(" sendto bytes=%d\n",bytes);
OLDEBUG("bytes=%d data=%s\n", bytes, buf_ptr);

	return(OK);
}


/*----------------------------------------------------------*/
/*			svr_data_rcv		*/
/* Receive RAW data  				*/
/*----------------------------------------------------------*/
int svr_data_rcv(ipc_t *ctrl_ipc, char *buf_ptr, int nbytes)
{
	int bytes;
	unsigned int addr_len;

    addr_len = sizeof (struct sockaddr_in);
	NO_EINTR(bytes = recvfrom(ctrl_ipc->socket,	/* Socket to receive */
			buf_ptr,							/* Receiving buffer */
			nbytes, 			   				/* Max recv buf size */
			0,              					/* Flags: no options */
			(struct sockaddr *)&ctrl_ipc->addr, /* Destination address */
			&addr_len));  						/* Addr len, in & out */
			
   	if( bytes < 0)
      	MOLERROR(" sendto bytes=%d\n",bytes);
OLDEBUG("bytes=%d data=%s\n", bytes, buf_ptr);

	return(OK);
}
